﻿using Engine;
using Engine.Graphics;
using Engine.Media;
using Game;
using System.Collections.Generic;

namespace Command
{
    public class OakLeavesBlock : Game.OakLeavesBlock
    {
        public new const int Index = 12;

        public static string CommandCategory = "命令方块彩色橡树叶";

        public override IEnumerable<int> GetCreativeValues()
        {
            List<int> creativeValues = new List<int>();
            if (SubsystemCommandDef.DisplayColorBlock)
            {
                for (int i = 0; i < 4096; i++)
                {
                    creativeValues.Add(Index + i * 32 * 16384);
                }
            }
            else
            {
                creativeValues.Add(Index);
            }
            return creativeValues;
        }

        public override string GetCategory(int value)
        {
            if (SubsystemCommandDef.DisplayColorBlock && value != Index) return CommandCategory;
            return base.GetCategory(value);
        }

        public override void GetDropValues(SubsystemTerrain subsystemTerrain, int oldValue, int newValue, int toolLevel, List<BlockDropValue> dropValues, out bool showDebris)
        {
            if (m_random.Bool(0.15f))
            {
                dropValues.Add(new BlockDropValue
                {
                    Value = 23,
                    Count = 1
                });
                showDebris = true;
            }
            else
            {
                Color leavesColor = GetCommandColor(Terrain.ExtractData(oldValue));
                if (IsDefaultColor(leavesColor))
                {
                    base.GetDropValues(subsystemTerrain, oldValue, newValue, toolLevel, dropValues, out showDebris);
                }
                else
                {
                    dropValues.Add(new BlockDropValue
                    {
                        Value = oldValue,
                        Count = 1
                    });
                    showDebris = true;
                }
            }
        }

        public override void GenerateTerrainVertices(BlockGeometryGenerator generator, TerrainGeometry geometry, int value, int x, int y, int z)
        {
            Color leavesColor = GetCommandColor(Terrain.ExtractData(value));
            if (IsDefaultColor(leavesColor))
            {
                leavesColor = BlockColorsMap.OakLeaves.Lookup(generator.Terrain, x, y, z);
            }
            Color color = leavesColor;
            generator.GenerateCubeVertices(this, value, x, y, z, color, geometry.AlphaTestSubsetsByFace);
        }

        public override void DrawBlock(PrimitivesRenderer3D primitivesRenderer, int value, Color color, float size, ref Matrix matrix, DrawBlockEnvironmentData environmentData)
        {
            Color leavesColor = GetCommandColor(Terrain.ExtractData(value));
            if (IsDefaultColor(leavesColor))
            {
                color *= BlockColorsMap.OakLeaves.Lookup(environmentData.Temperature, environmentData.Humidity);
            }
            else
            {
                color = leavesColor;
            }
            BlocksManager.DrawCubeBlock(primitivesRenderer, value, new Vector3(size), ref matrix, color, color, environmentData);
        }

        public override BlockDebrisParticleSystem CreateDebrisParticleSystem(SubsystemTerrain subsystemTerrain, Vector3 position, int value, float strength)
        {
            Color leavesColor = GetCommandColor(Terrain.ExtractData(value));
            if (IsDefaultColor(leavesColor))
            {
                leavesColor = BlockColorsMap.OakLeaves.Lookup(subsystemTerrain.Terrain, Terrain.ToCell(position.X), Terrain.ToCell(position.Y), Terrain.ToCell(position.Z));
            }
            Color color = leavesColor;
            return new BlockDebrisParticleSystem(subsystemTerrain, position, strength, DestructionDebrisScale, color, GetFaceTextureSlot(4, value));
        }

        public static Color GetCommandColor(int data)
        {
            int colorData = (data >> 5) & 0xFFF;
            int R = (colorData >> 8) & 0xF;
            int G = (colorData >> 4) & 0xF;
            int B = (colorData & 0xF);
            return new Color(R * 16, G * 16, B * 16) + new Color(15, 15, 15);
        }

        public static int SetCommandColor(int value, Color color)
        {
            color -= new Color(15, 15, 15);
            int R = (int)(color.R / 16f) << 8;
            int G = (int)(color.G / 16f) << 4;
            int B = (int)(color.B / 16f);
            int colorData = ((R | G | B) & 0xFFF) << 5;
            return Terrain.ReplaceData(value, colorData);
        }

        public static bool IsDefaultColor(Color color)
        {
            return color.R == 15 && color.G == 15 && color.B == 15;
        }
    }
}